package com.mybook.app.service;

import com.google.gson.Gson;
import com.mybook.app.conf.QiNiuConfig;
import com.mybook.app.core.UserContext;
import com.mybook.app.exception.FileUploadException;
import com.mybook.app.response.FileUpload;
import com.mybook.app.utils.Logger;
import com.mybook.app.utils.RandomUtils;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import static org.aspectj.weaver.tools.cache.SimpleCacheFactory.path;

/**
 * Created by zjutsw on 2017/11/2.
 * <p>
 * 文件上传
 */
@Service
public class FileUtilsService {
    @Autowired
    private QiNiuConfig qiNiuConfig;


    /**
     * 文件上传
     *
     * @param httpServletRequest
     * @return
     */
    public List<FileUpload> upload(HttpServletRequest httpServletRequest) {
        Logger.debug(this, "文件上传");
        List<FileUpload> uploads = new ArrayList<>();

        //获取文件byte
        List<byte[]> fileBytes = gainFile(httpServletRequest);
        if (CollectionUtils.isNotEmpty(fileBytes)) {
            fileBytes.forEach(bytes -> {
                StringBuilder path = new StringBuilder();
                path.append(qiNiuConfig.getPreUrl());
                path.append(fileUpQinQu(bytes, qiNiuConfig.getAccessKey(), qiNiuConfig.getSecretKey(), qiNiuConfig.getBucket(), qiNiuConfig.getPlatformName(), UserContext.getCurrentuserId().get()));
                FileUpload fileUploadResponse = new FileUpload();
                fileUploadResponse.setFileUrl(path.toString());
                fileUploadResponse.setUpFileTime(new Date());
                String[] paths = path.toString().split("/");
                fileUploadResponse.setFileName(paths[paths.length - 1]);
                uploads.add(fileUploadResponse);
            });
        }
        return uploads;
    }

    /**
     * 文件上传
     *
     * @param
     * @return
     */
    public FileUpload uploadMultipartFile(MultipartFile multipartFile) {
        StringBuilder path = new StringBuilder();
        path.append(qiNiuConfig.getPreUrl());
        path.append(fileUpQinQu(multipartFile, qiNiuConfig.getAccessKey(), qiNiuConfig.getSecretKey(), qiNiuConfig.getBucket(), qiNiuConfig.getPlatformName(), UserContext.getCurrentuserId().get()));
        FileUpload fileUploadResponse = new FileUpload();
        fileUploadResponse.setFileUrl(path.toString());
        fileUploadResponse.setUpFileTime(new Date());
        String[] paths = path.toString().split("/");
        fileUploadResponse.setFileName(paths[paths.length - 1]);
        return fileUploadResponse;
    }


    private List<byte[]> gainFile(HttpServletRequest httpServletRequest) {
        // 图片上传
        // 在解析请求之前先判断请求类型是否为文件上传类型
        List<byte[]> files = new ArrayList<>();
        boolean isMultipart = ServletFileUpload.isMultipartContent(httpServletRequest);
        InputStream is = null;
        if (isMultipart) {
            // 文件上传处理工厂
            FileItemFactory factory = new DiskFileItemFactory();
            // 创建文件上传处理器
            ServletFileUpload upload = new ServletFileUpload(factory);
            // 开始解析请求信息
            try {
                List<FileItem> items = upload.parseRequest(httpServletRequest);
                // 对所有请求信息进行判断
                Iterator iter = items.iterator();
                while (iter.hasNext()) {
                    FileItem item = (FileItem) iter.next();
                    files.add(item.get());
                }
            } catch (Exception ex) {
                Logger.warn(this, "图片上传失败", ex);
            }
        }
        return files;
    }


    private String fileUpQinQu(MultipartFile multipartFile, String accessKey, String secretKey, String bucket, String platformName, String userId) {
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone0());
        UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证，然后准备上传
        //默认不指定key的情况下，以文件内容的hash值作为文件名
        try {
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);
            StringBuilder builder = new StringBuilder();
            builder.append(platformName).append("/").append(userId).append("/").append(RandomUtils.randomNumber(4)).append(new String(multipartFile.getOriginalFilename().getBytes("ISO-8859-1")));
            Response response = uploadManager.put(multipartFile.getBytes(), builder.toString(), upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            return putRet.key;
        } catch (QiniuException ex) {
            Logger.error(this, "quniu 文件上传失败", ex);
            throw new FileUploadException();
        } catch (IOException ex) {
            Logger.error(this, "io exception", ex);
            throw new FileUploadException();
        }
    }

    private String fileUpQinQu(byte[] fileBytes, String accessKey, String secretKey, String bucket, String platformName, String userId) {
        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone0());
        UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证，然后准备上传
        //默认不指定key的情况下，以文件内容的hash值作为文件名
        try {
            Auth auth = Auth.create(accessKey, secretKey);
            String upToken = auth.uploadToken(bucket);

            StringBuilder builder = new StringBuilder();
            builder.append(platformName).append("/").append(userId).append("/").append(RandomUtils.randomNumber(4)).append(new String(/*multipartFile.getOriginalFilename().getBytes("ISO-8859-1")*/""));
            Response response = uploadManager.put(fileBytes, builder.toString(), upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            return putRet.key;
        } catch (QiniuException ex) {
            Logger.error(this, "quniu 文件上传失败", ex);
            throw new FileUploadException();
        } catch (IOException ex) {
            Logger.error(this, "io exception", ex);
            throw new FileUploadException();
        }
    }

}
